package com.t.bricks.bussiness.service.filestorage.impl;

import java.io.File;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.t.bricks.bussiness.model.filestorage.FileInfo;
import com.t.bricks.bussiness.service.filestorage.FileStorageService;
import com.t.bricks.model.Log;
import com.t.bricks.model.MsgEmity;
import com.t.bricks.utils.function.app.HttpServletUtil;
import com.t.bricks.utils.function.data.IntegerUtil;
import com.t.bricks.utils.function.file.FileUtil;
import com.t.bricks.utils.function.file.ZipUtil;

@Service
public class FileStorageServiceImpl implements FileStorageService {
	
	/**
	 * 文件上传及保存的根路径
	 */
	@Value("${UpFilePath:${user.dir}/data/user/filestorage}")
	private String filePathRoot;
	
	private boolean isInit = false;
	
	/**
	 * 取格式化后的根路径
	 * @return
	 */
	private String getFilePathRoot() {
		if (isInit) {
			return filePathRoot;
		}
		
		filePathRoot = filePathRoot.replaceAll("\\\\", "/");
		
		isInit = true;
		
		return filePathRoot;
	}
	
	/**
	 * 文件上传
	 * @param file 文件
	 * @param sPath 存储路径(不含文件名的相对路径)
	 * @param sFileName 存储的文件名
	 * @param iCover 是否覆盖(1:是;2:否)
	 * @return
	 */
	@Override
	public MsgEmity upFile(MultipartFile file, String sPath, String sFileName,
			Integer iCover) {
		if (null == sPath || "".equals(sPath.trim())) {
			return MsgEmity.err(8001, "请求存储的路径为空");
		}
		
		sPath = sPath.trim().replaceAll("\\\\", "/");
		File temp = new File(sPath);
		if (temp.isDirectory() || temp.isFile()) {
			return MsgEmity.err(8002, "出于安全考虑,请求存储的路径不能是绝对路径");
		}
		
		if (null == sFileName || "".equals(sFileName.trim())) {
			sFileName = file.getOriginalFilename();
		} else if(!sFileName.matches("[^/\\\\<>*?|\"]+\\.[^/\\\\<>*?|\"]+")) {
			return MsgEmity.err(8003, "指定的文件名不合法");
		}
		
		String savePath = new StringBuilder()
			.append(getFilePathRoot()).append("/")
			.append(sPath).append("/")
			.append(sFileName.trim())
			.toString().replaceAll("//", "/");
		
		File saveFile = new File(savePath);
		if (saveFile.exists() && IntegerUtil.objToInt(iCover, 2) != 1) {
			return MsgEmity.err(8004, "存在同名文件,放弃保存");
		}
		
		if (!saveFile.getParentFile().exists()) {
			saveFile.getParentFile().mkdirs();
		}
		
		try {
			file.transferTo(saveFile);
		} catch (Exception e) {
			Log.error("文件保存发生异常:", e.getMessage());
			return MsgEmity.err(8005, "文件保存发生异常:", e.getMessage());
		}
		
		if (!saveFile.exists()) {
			return MsgEmity.err(8006, "文件保存失败");
		}
		
		savePath = savePath.replace(getFilePathRoot(), "");//去除根路径,以获得相对路径
		
		return new MsgEmity(true, "文件保存成功", savePath);
	}
	
	/**
	 * 判断文件是否存在
	 * @param sPath 存储路径(含文件名的相对路径)
	 * @return
	 */
	@Override
	public MsgEmity checkFile(String sPath) {
		if (null == sPath) {
			sPath = "";
		}
		
		String filePath = new StringBuilder()
			.append(getFilePathRoot()).append("/")
			.append(sPath.trim())
			.toString().replaceAll("//", "/");
		
		File file = new File(filePath);
		if (!file.exists()) {
			return MsgEmity.err(8001, "未找到文件");
		}
		
		return MsgEmity.success(8999, "文件存在");
	}
	
	/**
	 * 读取文件内容
	 * @param sPath 存储路径(含文件名的相对路径)
	 * @return
	 */
	@Override
	public MsgEmity readFile(String sPath) {
		if (null == sPath) {
			sPath = "";
		}
		
		String filePath = new StringBuilder()
			.append(getFilePathRoot()).append("/")
			.append(sPath.trim())
			.toString().replaceAll("//", "/");
		
		File file = new File(filePath);
		if (!file.exists()) {
			return MsgEmity.err(8001, "未找到文件");
		}
		
		MsgEmity me = FileUtil.readFile(filePath);
		if (!me.isSuccess()) {
			return me;
		}
		
		String txt = me.getData();
		if (null == txt) {
			return MsgEmity.err(8002, "读取文件失败");
		}
		
		return new MsgEmity(true, "读取文件成功", txt);
	}
	
	/**
	 * 删除文件
	 * @param sPath 存储路径(含文件名的相对路径)
	 * @return
	 */
	@Override
	public MsgEmity delFile(String sPath) {
		if (null == sPath) {
			sPath = "";
		}
		
		String filePath = new StringBuilder()
			.append(getFilePathRoot()).append("/")
			.append(sPath.trim())
			.toString().replaceAll("//", "/");
		
		File file = new File(filePath);
		if (!file.exists()) {
			return MsgEmity.success(8999, "文件本身不存在");
		}
		
		boolean bl = file.delete();
		if (!bl) {
			return MsgEmity.err(8001, "删除失败,请检查文件是否在占用中");
		}
		
		//if (file.getParentFile().list().length < 1) {
		//	file.getParentFile().delete();
		//}
		
		return MsgEmity.success(8999, "删除文件成功");
	}
	
	/**
	 * 下载文件
	 * @param request request对象
	 * @param response response对象
	 * @param sPath 存储路径(含文件名的相对路径)
	 */
	@Override
	public void download(Object request, Object response, String sPath) {
		if (null == sPath) {
			sPath = "";
		}
		
		String filePath = new StringBuilder()
			.append(getFilePathRoot()).append("/")
			.append(sPath.trim())
			.toString().replaceAll("//", "/");
		
		File file = new File(filePath);
		if (!file.exists()) {
			HttpServletUtil.setTxt(response, MsgEmity.err(8001, "未找到文件"));
			return;
		}
		
		HttpServletUtil.downloadFile(request, response, filePath, file.getName());
	}
	
	/**
	 * 下载文件zip
	 * @param sPath 存储路径(含文件名的相对路径)
	 * @return
	 */
	@Override
	public MsgEmity downloadZip(String sPath) {
		if (null == sPath) {
			sPath = "";
		}
		
		String filePath = new StringBuilder()
			.append(getFilePathRoot()).append("/")
			.append(sPath.trim())
			.toString().replaceAll("//", "/");
		
		File file = new File(filePath);
		if (!file.exists()) {
			return MsgEmity.err(8001, "未找到文件");
		}
		
		MsgEmity me = FileUtil.readToBase64(filePath);
		if (!me.isSuccess()) {
			return me;
		}
		
		me = ZipUtil.zipStr((String)me.getData());//将内容进行压缩,便于传输
		if (!me.isSuccess()) {
			return me;
		}
		return me.setMsg(file.getName());
	}
	
	/**
	 * 读取文件目录
	 * @param sPath 存储路径
	 * @return MsgEmity 返回查询结果
	 */
	@Override
	public MsgEmity findByTree(String sPath) {
		if (null == sPath) {
			sPath = "";
		}
		
		String filePath = new StringBuilder()
			.append(getFilePathRoot()).append("/")
			.append(sPath.trim())
			.toString().replaceAll("//", "/");
		
		File file = new File(filePath);
		FileInfo result = new FileInfo(file);
		result.setsPath(result.getsPath().replaceAll("\\\\", "/").replace(getFilePathRoot(), ""));
		result.setClient(findClient(file));
		
		return new MsgEmity(true, "读取结束", result);
	}
	
	/**
	 * 取子文件信息
	 * @param dir
	 * @return
	 */
	private FileInfo[] findClient(File dir) {
		if (null == dir) {
			return null;
		}

		//--如果是文件--//
		if (dir.isFile()) {
			return null;
		}
		
		//--如果是目录--//
		File[] list = dir.listFiles();
		if (null == list || list.length < 1) {
			return null;
		}
		
		FileInfo[] result = new FileInfo[dir.listFiles().length];
		for (int i = 0; i < dir.listFiles().length; i++) {
			File file = dir.listFiles()[i];
			FileInfo fileInfo = new FileInfo(file);
			result[i] = fileInfo;
			fileInfo.setsPath(fileInfo.getsPath().replaceAll("\\\\", "/").replace(getFilePathRoot(), ""));
			
			if (!file.isDirectory()) {
				continue;
			}
			
			FileInfo[] subList = findClient(file);//递归
			if (null == subList) {
				continue;
			}
			
			fileInfo.setClient(subList);
		}
		
		return result;
	}
	
}
